/*
 * Copyright (c) 2003-2010, Live Media Pty. Ltd.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, this list of
 *     conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice, this list of
 *     conditions and the following disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *  3. Neither the name of Live Media nor the names of its contributors may be used to endorse
 *     or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.colony.transport.socket;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import java.net.ServerSocket;
import java.net.Socket;

import com.argot.network.TypeLink;
import com.argot.remote.transport.TypeEndPoint;

import com.colony.transport.Server;
import com.colony.concurrent.ThreadActivator;


public class SocketServer
extends Server
{
	private ServerSocket _socket;
	private boolean _isClosed;
	
	public SocketServer( TypeLink back, ThreadActivator pool, ServerSocket socket )
	{
		super( back, pool );
		_socket = socket;
		_isClosed = false;
	}

	public SocketServer( ThreadActivator pool, ServerSocket socket )
	{
		this( null, pool, socket );
	}
	
	/**
	 * Method connect. This sets up a thread to wait on connections
	 * It must be called after the Node is setup in a Zone.
	 */
	public boolean connect()
	{
     	return getPool().assignThread( new SocketServerWorker() );
	}
	
	public void disconnect() throws IOException
	{
		_isClosed = true;
		_socket.close();
	}

   private class SocketServerWorker
   implements Runnable
   {
   	public void run()
   	{
   		try
   		{
   			connectServer();
   		}
   		catch( IOException ex )
   		{
   			if ( !_isClosed )
   			{
   				// Need to pass in String for Java 1.4
   				throw new IllegalStateException(ex.toString());
   			}
   		}
   	}
   }

   private void connectServer(  )
   throws IOException
   {

		while ( true )
		{
			Socket clientSocket = _socket.accept();
			InputStream input = clientSocket.getInputStream();
			OutputStream output = clientSocket.getOutputStream();
       	 
			boolean assigned = assignServerThread( new SocketRequest( new BufferedInputStream(input), new BufferedOutputStream(output), clientSocket) );
			if ( !assigned )
				System.err.println( "Error: failed to assign thread" );
      }
   }
   
	protected void processFinish( TypeEndPoint req ) 
	{
		SocketRequest request = (SocketRequest) req;
		Socket socket = request.getSocket();
		try 
		{
			socket.shutdownOutput();
		} 
		catch (IOException e) 
		{
			// do nothing.
		}

		try 
		{
			socket.close();
		} 
		catch (IOException e) 
		{
			// do nothing.
		} 		
	}

}
